#include "loader.h"
#include "parser.h"
using namespace std;

/*
 * Construtor da classe: abre um novo stream de entrada de nome 'filename'
 */
Loader::Loader(char *filename)
{
	in.open(filename);
}

/*
 * Destrutor da classe: fecha o stream de entrada aberto pelo construtor
 */
Loader::~Loader()
{
	in.close();
}

/*
 * Faz a leitura de blocos de texto do stream de entrada e retorna
 * 	o nnumero de bytes lidos
 */
int Loader::readBlock(short mode, int block_size)
{
	char *buffer = new char[block_size + 1];
	in.read(buffer, block_size);
	buffer[block_size] = '\0';
	extern string *inputData;
	inputData = new string(buffer);

	int gcount = in.gcount();
	bool last_iteration;
	if (block_size != BLOCK_SIZE)
		last_iteration = true;
	else
		last_iteration = false;

	if (mode == WORDS) {
		/* se o metodo de execucao for WORDS garante que a ultima palavra nao seja lida
		 * 	pela metade */
		getEndOfTheWord(inputData, last_iteration, &gcount);
	}
	else {
		/* se o metodo de execucao for WORDS_PHRASES garante que a ultima frase seja lida
		 * 	ate o final
		 */
		getEndOfThePhrase(inputData, last_iteration, &gcount);
	}

	/* remove espacos e '\n' desnecessarios */
	removeSpaces(inputData);

	(*inputData) += " ";

	/* libera memoria alocada para a string 'buffer' */
	delete[] buffer;
	buffer = NULL;

	return gcount;
}

/*
 * Retorna o tamanho total do stream de entrada
 */
int Loader::tellLength()
{
	in.seekg(0, ios::end);
	int length = in.tellg();
	in.seekg(0, ios::beg);

	return length;
}

/*
 * Metodo que garante que a ultima palavra lida nao esteja pela metade
 */
void Loader::getEndOfTheWord(string *str, bool last_iteration, int *gcount)
{
	string::iterator it = str->end();
	if (isalnum(*it) && !last_iteration) {
		char c = in.get();
		(*gcount)++;
		while (isalnum(c)) {
			(*str) += c;
			(*gcount)++;
			c = in.get();
		}
	}
}

/*
 * Metodo que garante que a ultima frase lida seja termine com uma pontuacao
 * 	de final de frase (garantindo que a frase nao esteja pela metade)
 */
void Loader::getEndOfThePhrase(string *str, bool last_iteration, int *gcount)
{
	extern int readed;
	string::iterator it = str->end();
	if ((*it != '.' && *it != '?' && *it != '!' ) && !last_iteration) {
		char c = in.get();
		(*gcount)++;
		while (c != '.' && c != '?' && c != '!') { //isalpha(c)
			(*str) += c;
			c = in.get();
			(*gcount)++;
			if (c == '.' || c == '?' || c == '!')
				in.seekg(readed + (*gcount), ios::beg);
		}
	}
}

/*
 * Remove espacos, hifens e '\n' desnecessarios do bloco lido
 */
void Loader::removeSpaces(string *str)
{
	string::iterator it = str->begin();
	while (it + 1 != str->end()) {
		/* remove hifens */
		if (*it == '-') {
			str->erase(it);
			it--;
		}
		/* remove quebras de linha seguidas */
		else if (*it == '\n' && *(it + 1) == '\n') {
			str->erase(it);
			it--;
		}
		/* remove espacos seguidos */
		else if (*it == ' ' && *(it + 1) == ' ') {
			str->erase(it);
			it--;
		}
		/* remove o espaco apos a pontuacao */
		else if ((*it == '.' || *it == '?' || *it == '!') && (*(it + 1) == ' ' || *(it + 1) == '\n')) {
			str->erase(it + 1);
			it--;
		}
		/* remove o TAB */
		else if (*it == 9) {
			str->erase(it);
			it--;
		}
		else {
			it++;
		}
	}
}
